/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ibmmodel3;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * @author mwh
 */
public class Aligner {

    public static void test(int m) {
        System.err.println(choose(2, 3));
        System.err.println("m\tphi0\tm-phi0");
        for (int phi0 = 0; phi0 <= m; phi0++) {
            int mp=m-phi0;
            
            System.err.println(m + "\t" + phi0 + "\t" + mp +"\t"+ choose(mp,phi0));
        }
    }


    public static void align(GIZAAlignment ga) {

        Set<Alignment> possibleAligments = new HashSet();

        for (int s = 1; s <= ga.ss1.size(); s++) {
            for (int t = 1; t <= ga.ss2.size(); t++) {
                possibleAligments.add(new Alignment(s, t));
            }
        }

        double current = ga.score();

        Alignment b = null;
        double bestScore = current;
        alignRes best = null;

        boolean improved = true;
        while (improved) {
            improved = false;
            for (Alignment ca : possibleAligments) {

              //  System.err.println("Trying " + ca);
                alignRes ar = ga.tryAlign(ca.source, ca.target,false);
                double score = ar.res;

                if (score > bestScore) {
                    best = ar;
                    b = new Alignment(ca.source, ca.target);
                    bestScore = score;
                }
            }

            if (bestScore > current) {
                improved = true;
                ga.apply(best);
                //ga.addAlignment(b.source, b.target);
                for (Iterator<Alignment> it = possibleAligments.iterator(); it.hasNext();) {
                    Alignment ra = it.next();
                    if (ra.target == b.target) {
                        it.remove();
                    }
                }
                current = bestScore;

            }
        }
     //   System.err.println(possibleAligments);
    }
    // Compute n choose k, which is the number of ways you can choose k objects
    // out of a set of n.  It is equal to n! / (k! * (n-k)!) .
    private static long choose(int n, int k) {
        return fact(n) / (fact(k) * fact(n - k));
    }

    // Compute n!.
    private static long fact(int n) {
        long answer = 1;    // Accumulate the product

        for (long i = 1; i <= n; i++) {
            answer *= i;
        }

        return answer;
    }
}
